#include "simulation.h"

FCFSSimulation::FCFSSimulation(int argc, char **argv) : Simulation(argc, argv) {

}

//schedule a departure event for a given customer
void FCFSSimulation::schedule_departure(Customer *customer) {
	//set the service time
	Ts = expntl(1/mu, kSeed_service);
	customer->service_time_ = Ts;
	//create a departure event and add it to the event list
	EventNode *current_departure = new EventNode('D', customer, sim_time + Ts);
	event_list_add(current_departure);
}

//process an arrival event
void FCFSSimulation::process_arrival(EventNode *next_event) {
	//generate the next inter-arrival time
	Ta = expntl(1/lambda, kSeed_arrival);
	//set the simulation time to the time of the next event
	sim_time = next_event->time_;
	
	if (n < kcpu) {
		arrival_count++;
		customer_queue.push_back(next_event->customer_);
		n++;
		if (n == 1) {
			schedule_departure(customer_queue.front());
		}
		Customer *customer = new Customer(total_arrival_count++, sim_time + Ta, 0, 0, 0, false, false); 
		customer_list.push_back(customer);
		EventNode *next_arrival = new EventNode('A', customer, sim_time + Ta);
		event_list_add(next_arrival);

	} else {
		next_event->customer_->lost_ = true;
		next_event->customer_->serviced_ = false;
		EventNode *lost_arrival = new EventNode('L', next_event->customer_, sim_time);
		event_list_add(lost_arrival);
	}
}

//process the lost event
void FCFSSimulation::process_lost(EventNode *next_event) {
	//generate the next inter-arrival time
	Ta = expntl(1/lambda, kSeed_arrival);
	//set the simulation time to the time of the next event
	sim_time = next_event->time_;
	//create a new customer for the next arrival and add it to the event list
	Customer *customer = new Customer(total_arrival_count++, sim_time + Ta, 0, 0, 0, false, false); 
	customer_list.push_back(customer);
	if (n < kcpu) {
		EventNode *next_arrival = new EventNode('A', customer, sim_time + Ta);
		event_list_add(next_arrival);

	} else {
		customer->lost_ = true;
		customer->serviced_ = false;
		EventNode *lost_arrival = new EventNode('L', customer, sim_time + Ta);
		event_list_add(lost_arrival);
	}
}

void FCFSSimulation::process_departure(EventNode *next_event) {
	if (! customer_queue.empty()) {
		Customer *departing_customer = next_event->customer_;
		sim_time = next_event->time_;
		departing_customer->departure_time_ = sim_time;
		departing_customer->serviced_ = true;
		departing_customer->lost_ = false;
		departing_customer->departure_number_ = ++departure_count;
		customer_queue.pop_front();
		departing_customer->customers_after_ = customer_queue.size();
		n--;
		serve_count++;
		if (n > 0) {
			schedule_departure(customer_queue.front());
		}
	} 
}

